/*
 * Copyright 2024 ywcai
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

`include "defines.v"
`include "../perips/axi_defines.v"
`timescale 1ns/1ps

module bus_ctrl(
	input	wire						clk,
	input	wire						rst_n,

	input	wire						m0_req_i,
	input	wire						m0_we_i,
    input	wire[`MemAddrBus]			m0_addr_i,
    input	wire[`CacheBus]				m0_wr_data_i,
	input	wire[`CACHE_BITS/8-1:0]		m0_strb_i,
	input	wire[11:0]					m0_pulse_bits_i,

	input	wire						m1_req_i,
	input	wire						m1_we_i,
    input	wire[`MemAddrBus]			m1_addr_i,
    input	wire[`CacheBus]				m1_wr_data_i,
	input	wire[`CACHE_BITS/8-1:0]		m1_strb_i,
	input	wire[11:0]					m1_pulse_bits_i,

	input	wire						m2_req_i,
	input	wire						m2_we_i,
    input	wire[`MemAddrBus]			m2_addr_i,
    input	wire[`CacheBus]				m2_wr_data_i,
	input	wire[`CACHE_BITS/8-1:0]		m2_strb_i,
	input	wire[11:0]					m2_pulse_bits_i,

	input	wire						m3_req_i,
	input	wire						m3_we_i,
    input	wire[`MemAddrBus]			m3_addr_i,
    input	wire[`CacheBus]				m3_wr_data_i,
	input	wire[`CACHE_BITS/8-1:0]		m3_strb_i,
	input	wire[11:0]					m3_pulse_bits_i,

	input	wire[`RegDataBus]			s0_rd_data_i,
	input	wire[1:0]					s0_errcode_i,
	input	wire[`RegDataBus]			s1_rd_data_i,
	input	wire[1:0]					s1_errcode_i,
	input	wire[`RegDataBus]			s2_rd_data_i,
	input	wire[1:0]					s2_errcode_i,
	input	wire[`RegDataBus]			s3_rd_data_i,
	input	wire[1:0]					s3_errcode_i,
	input	wire[`RegDataBus]			s4_rd_data_i,
	input	wire[1:0]					s4_errcode_i,
	input	wire[`RegDataBus]			s5_rd_data_i,
	input	wire[1:0]					s5_errcode_i,
	input	wire[`RegDataBus]			s6_rd_data_i,
	input	wire[1:0]					s6_errcode_i,
	input	wire[`RegDataBus]			s7_rd_data_i,
	input	wire[1:0]					s7_errcode_i,

	output	wire[`CacheBus]				m0_rd_data_o,
	output	wire[1:0]					m0_errcode_o,

	output	wire[`CacheBus]				m1_rd_data_o,
	output	wire[1:0]					m1_errcode_o,

	output	wire[`CacheBus]				m2_rd_data_o,
	output	wire[1:0]					m2_errcode_o,

	output	wire[`CacheBus]				m3_rd_data_o,
	output	wire[1:0]					m3_errcode_o,

    output  wire               			s0_we_o,
	output	wire[`MemAddrBus]			s0_addr_o,
	output	wire[`RegDataBus]			s0_wr_data_o,
	output	wire[7:0]					s0_strb_o,

    output  wire                		s1_we_o,
	output	wire[`MemAddrBus]			s1_addr_o,
	output	wire[`RegDataBus]			s1_wr_data_o,
	output	wire[7:0]					s1_strb_o,

    output  wire                		s2_we_o,
	output	wire[`MemAddrBus]			s2_addr_o,
	output	wire[`RegDataBus]			s2_wr_data_o,
	output	wire[7:0]					s2_strb_o,

    output  wire                		s3_we_o,
	output	wire[`MemAddrBus]			s3_addr_o,
	output	wire[`RegDataBus]			s3_wr_data_o,
	output	wire[7:0]					s3_strb_o,

    output  wire                		s4_we_o,
	output	wire[`MemAddrBus]			s4_addr_o,
	output	wire[`RegDataBus]			s4_wr_data_o,
	output	wire[7:0]					s4_strb_o,

    output  wire                		s5_we_o,
	output	wire[`MemAddrBus]			s5_addr_o,
	output	wire[`RegDataBus]			s5_wr_data_o,
	output	wire[7:0]					s5_strb_o,

    output  wire                		s6_we_o,
	output	wire[`MemAddrBus]			s6_addr_o,
	output	wire[`RegDataBus]			s6_wr_data_o,
	output	wire[7:0]					s6_strb_o,

    output  wire                		s7_we_o,
	output	wire[`MemAddrBus]			s7_addr_o,
	output	wire[`RegDataBus]			s7_wr_data_o,
	output	wire[7:0]					s7_strb_o,

	output	wire						req_result_o,
	output	wire						transact_done_o
	);

	wire				m0_m_bus_grant;
	wire				m0_io_bus_grant;
	wire				m1_m_bus_grant;
	wire				m1_io_bus_grant;
	wire				m2_m_bus_grant;
	wire				m2_io_bus_grant;
	wire				m3_m_bus_grant;
	wire				m3_io_bus_grant;

	wire[`CacheBus]		m0_m_rd_data;
	wire[1:0]			m0_m_rd_errcode;
	wire				m0_m_transact_done;

	wire[`CacheBus]		m0_io_rd_data;
	wire[1:0]			m0_io_rd_errcode;
	wire				m0_io_transact_done;

	assign transact_done_o =
		m0_m_transact_done | m0_io_transact_done;
	assign m0_rd_data_o =
		({`CACHE_BITS{m0_m_transact_done}} & m0_m_rd_data)
		| ({`CACHE_BITS{m0_io_transact_done}} & m0_io_rd_data);
	assign m0_errcode_o =
		({2{m0_m_transact_done}} & m0_m_rd_errcode)
		| ({2{m0_io_transact_done}} & m0_io_rd_errcode);

	bus_arbiter i_bus_arbiter(
		.clk(clk),
		.rst_n(rst_n),
		.m0_req_i(m0_req_i),
		.m0_addr_i(m0_addr_i),
		.m1_req_i(m1_req_i),
		.m1_addr_i(m1_addr_i),
		.m2_req_i(m2_req_i),
		.m2_addr_i(m2_addr_i),
		.m3_req_i(m3_req_i),
		.m3_addr_i(m3_addr_i),
		.transact_done_i(transact_done_o),
		.m0_m_bus_grant_o(m0_m_bus_grant),
		.m0_io_bus_grant_o(m0_io_bus_grant),
		.m1_m_bus_grant_o(m1_m_bus_grant),
		.m1_io_bus_grant_o(m1_io_bus_grant),
		.m2_m_bus_grant_o(m2_m_bus_grant),
		.m2_io_bus_grant_o(m2_io_bus_grant),
		.m3_m_bus_grant_o(m3_m_bus_grant),
		.m3_io_bus_grant_o(m3_io_bus_grant)
	);

	axi_bus_bridge i_m_bus(
		.clk(clk),
		.rst_n(rst_n),
		.m0_req_i(m0_req_i),
		.m0_we_i(m0_we_i),
		.m0_addr_i(m0_addr_i),
		.m0_wr_data_i(m0_wr_data_i),
		.m0_strb_i(m0_strb_i),
		.m0_pulse_bits_i(m0_pulse_bits_i),
		.m0_m_bus_grant_i(m0_m_bus_grant),
		.m0_io_bus_grant_i(`DISABLE),
		.m1_req_i(m1_req_i),
		.m1_we_i(m1_we_i),
		.m1_addr_i(m1_addr_i),
		.m1_wr_data_i(m1_wr_data_i),
		.m1_strb_i(m1_strb_i),
		.m1_pulse_bits_i(m1_pulse_bits_i),
		.m1_m_bus_grant_i(m1_m_bus_grant),
		.m1_io_bus_grant_i(`DISABLE),
		.m2_req_i(m2_req_i),
		.m2_we_i(m2_we_i),
		.m2_addr_i(m2_addr_i),
		.m2_wr_data_i(m2_wr_data_i),
		.m2_strb_i(m2_strb_i),
		.m2_pulse_bits_i(m2_pulse_bits_i),
		.m2_m_bus_grant_i(m2_m_bus_grant),
		.m2_io_bus_grant_i(`DISABLE),
		.m3_req_i(m3_req_i),
		.m3_we_i(m3_we_i),
		.m3_addr_i(m3_addr_i),
		.m3_wr_data_i(m3_wr_data_i),
		.m3_strb_i(m3_strb_i),
		.m3_pulse_bits_i(m3_pulse_bits_i),
		.m3_m_bus_grant_i(m3_m_bus_grant),
		.m3_io_bus_grant_i(`DISABLE),
		.s0_rd_data_i(),
        .s0_errcode_i(),
		.s1_rd_data_i(s1_rd_data_i),
		.s1_errcode_i(s1_errcode_i),
		.s2_rd_data_i(),
        .s2_errcode_i(),
		.s3_rd_data_i(),
        .s3_errcode_i(),
		.s4_rd_data_i(s4_rd_data_i),
		.s4_errcode_i(s4_errcode_i),
		.s5_rd_data_i(),
        .s5_errcode_i(),
		.s6_rd_data_i(),
        .s6_errcode_i(),
		.s7_rd_data_i(),
        .s7_errcode_i(),
		.m0_rd_data_o(m0_m_rd_data),
		.m0_errcode_o(m0_m_rd_errcode),
		.m1_rd_data_o(),
		.m1_errcode_o(),
		.m2_rd_data_o(),
		.m2_errcode_o(),
		.m3_rd_data_o(),
		.m3_errcode_o(),
        .s0_we_o(),
		.s0_addr_o(),
		.s0_wr_data_o(),
		.s0_strb_o(),
        .s1_we_o(s1_we_o),
		.s1_addr_o(s1_addr_o),
		.s1_wr_data_o(),
		.s1_strb_o(),
        .s2_we_o(),
		.s2_addr_o(),
		.s2_wr_data_o(),
		.s2_strb_o(),
        .s3_we_o(),
		.s3_addr_o(),
		.s3_wr_data_o(),
		.s3_strb_o(),
        .s4_we_o(s4_we_o),
		.s4_addr_o(s4_addr_o),
		.s4_wr_data_o(s4_wr_data_o),
		.s4_strb_o(s4_strb_o),
        .s5_we_o(),
		.s5_addr_o(),
		.s5_wr_data_o(),
		.s5_strb_o(),
        .s6_we_o(),
		.s6_addr_o(),
		.s6_wr_data_o(),
		.s6_strb_o(),
        .s7_we_o(),
		.s7_addr_o(),
		.s7_wr_data_o(),
		.s7_strb_o(),
		.transact_done_o(m0_m_transact_done)
	);

	axi_bus_bridge i_io_bus(
		.clk(clk),
		.rst_n(rst_n),
		.m0_req_i(/*m0_req_i*/),
		.m0_we_i(/*m0_we_i*/),
		.m0_addr_i(/*m0_addr_i*/),
		.m0_wr_data_i(/*m0_wr_data_i*/),
		.m0_strb_i(/*m0_strb_i*/),
		.m0_pulse_bits_i(/*m0_pulse_bits_i*/),
		.m0_m_bus_grant_i(/*`DISABLE*/),
		.m0_io_bus_grant_i(/*m0_io_bus_grant*/),
		.m1_req_i(m1_req_i),
		.m1_we_i(m1_we_i),
		.m1_addr_i(m1_addr_i),
		.m1_wr_data_i(m1_wr_data_i),
		.m1_strb_i(m1_strb_i),
		.m1_pulse_bits_i(m1_pulse_bits_i),
		.m1_m_bus_grant_i(`DISABLE),
		.m1_io_bus_grant_i(m1_io_bus_grant),
		.m2_req_i(m2_req_i),
		.m2_we_i(m2_we_i),
		.m2_addr_i(m2_addr_i),
		.m2_wr_data_i(m2_wr_data_i),
		.m2_strb_i(m2_strb_i),
		.m2_pulse_bits_i(m2_pulse_bits_i),
		.m2_m_bus_grant_i(`DISABLE),
		.m2_io_bus_grant_i(m2_io_bus_grant),
		.m3_req_i(m3_req_i),
		.m3_we_i(m3_we_i),
		.m3_addr_i(m3_addr_i),
		.m3_wr_data_i(m3_wr_data_i),
		.m3_strb_i(m3_strb_i),
		.m3_pulse_bits_i(m3_pulse_bits_i),
		.m3_m_bus_grant_i(`DISABLE),
		.m3_io_bus_grant_i(m3_io_bus_grant),
		.s0_rd_data_i(),
        .s0_errcode_i(),
		.s1_rd_data_i(),
		.s1_errcode_i(),
		.s2_rd_data_i(),
        .s2_errcode_i(),
		.s3_rd_data_i(),
        .s3_errcode_i(),
		.s4_rd_data_i(),
		.s4_errcode_i(),
		.s5_rd_data_i(),
        .s5_errcode_i(),
		.s6_rd_data_i(),
        .s6_errcode_i(),
		.s7_rd_data_i(),
        .s7_errcode_i(),
		.m0_rd_data_o(m0_io_rd_data),
		.m0_errcode_o(m0_io_rd_errcode),
		.m1_rd_data_o(),
		.m1_errcode_o(),
		.m2_rd_data_o(),
		.m2_errcode_o(),
		.m3_rd_data_o(),
		.m3_errcode_o(),
        .s0_we_o(),
		.s0_addr_o(),
		.s0_wr_data_o(),
		.s0_strb_o(),
        .s1_we_o(),
		.s1_addr_o(),
		.s1_wr_data_o(),
		.s1_strb_o(),
        .s2_we_o(),
		.s2_addr_o(),
		.s2_wr_data_o(),
		.s2_strb_o(),
        .s3_we_o(),
		.s3_addr_o(),
		.s3_wr_data_o(),
		.s3_strb_o(),
        .s4_we_o(),
		.s4_addr_o(),
		.s4_wr_data_o(),
		.s4_strb_o(),
        .s5_we_o(),
		.s5_addr_o(),
		.s5_wr_data_o(),
		.s5_strb_o(),
        .s6_we_o(),
		.s6_addr_o(),
		.s6_wr_data_o(),
		.s6_strb_o(),
        .s7_we_o(),
		.s7_addr_o(),
		.s7_wr_data_o(),
		.s7_strb_o(),
		.transact_done_o(m0_io_transact_done)
	);

endmodule
